#pragma once

#include "PLObject.h"
#include "PLVertex.h"

#include <set>

/**
  *	The PLVertexFactory is implemented as a singleton, therefore only one instance
  * exists that is used as a manager of PLVertex objects. PLVertex objects can be
  * borrowed (via BorrowVertex()) and returned (via ReturnVertex()).
  */
class PLVertexFactory : public PLObject
{
public:
	static PLVertexFactory *Get( void );
	PLuint GetMaxUsageOfVertex( void ) const;
	PLuint GetMinUsageOfVertex( void ) const;
	PLuint GetNumberOfBorrowedVertexes( void ) const;
	PLuint GetSumBorrows( void ) const;
	bool HasUsageOneForVertex( PLuint *vertexIndex, PLuint *texcoordIndex, PLuint *textureID );
	PLVertex *BorrowVertex( PLuint vertexIndex, PLuint texcoordIndex, PLuint textureID );
	void ReturnVertex( PLVertex *vertex );

private:
	PLVertexFactory( void );
	~PLVertexFactory( void );

	/**
	  * A PLVertexNumPair object capsules a pointer to a PLVertex object an its
	  * corresponding usage number.
	  */
	struct PLVertexNumPair
	{
		/**
		  *	Constructs a new PLVertexNumPair object with the given arguments
		  * @param vertex pointer to the PLVertex object
		  * @param num usage number of the PLVertex object
		  */
		PLVertexNumPair( PLVertex *vertex, PLuint num ) :
			mVertex(vertex), mNum(num) {};

		/** pointer to the PLVertex object */
		PLVertex *mVertex;
		/** usage number of the PLVertex object */
		PLuint mNum;
	};

	/**
	  *	PLVertexNumPairPCompare objects are used as Compare-objects in
	  * stl containers
	  */
	static class PLVertexNumPairPCompare
	{
		public:
			bool operator()(const PLVertexNumPair *first, const PLVertexNumPair *second) const;
	};

	/** Pointer to the one and only instance of PLVertexFactory */
	static PLVertexFactory *mFactory;
	
	/** Set of pointers to all the PLVertexNumPair objects */
	std::set<PLVertexNumPair*, PLVertexFactory::PLVertexNumPairPCompare> mUsedVertexes;
};